<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>杭州二手房房价趋势分析</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js "></script>
  <style>
    body {
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
      background-color: #f4f6f9;
      margin: 0;
      padding: 20px;
    }
    h1 {
      text-align: center;
      color: #333;
    }
    .chart-container {
      position: relative;
      margin: auto;
      width: 90%;
      max-width: 1200px;
      height: 700px;
      background: white;
      border-radius: 12px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
      padding: 20px;
      margin-bottom: 30px;
    }
    
    .model-metrics {
      width: 90%;
      max-width: 1200px;
      margin: 30px auto;
      padding: 20px;
      background-color: white;
      border-radius: 12px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    }
    
    .metrics-container {
      display: flex;
      justify-content: space-between;
      margin: 20px 0;
      flex-wrap: wrap;
      gap: 20px;
    }
    
    .metric-card {
      flex: 1;
      min-width: 250px;
      padding: 20px;
      background-color: #f8f9fa;
      border-radius: 8px;
      box-shadow: 0 2px 4px rgba(0,0,0,0.05);
    }
    
    .metric-title {
      font-weight: bold;
      color: #495057;
      margin-bottom: 10px;
      font-size: 16px;
    }
    
    .metric-value {
      font-size: 24px;
      color: #4CAF50;
      margin-bottom: 10px;
      font-weight: bold;
    }
    
    .metric-desc {
      font-size: 14px;
      color: #6c757d;
      line-height: 1.4;
    }
    
    .model-notes {
      margin-top: 30px;
      padding: 20px;
      background-color: #f8f9fa;
      border-radius: 8px;
      border-left: 4px solid #4CAF50;
    }
    
    .model-notes h4 {
      color: #495057;
      margin-top: 0;
      margin-bottom: 15px;
    }
    
    .model-notes p {
      color: #6c757d;
      line-height: 1.6;
      margin-bottom: 10px;
    }
    
    #refreshBtn:hover {
      background-color: #45a049;
    }
    
    #refreshBtn:active {
      background-color: #3d8b40;
    }
    
    #predictionStatus {
      transition: all 0.3s ease;
    }
  </style>
</head>
<body>

<h1>杭州二手房房价趋势深度分析（2010-2030）</h1>
<div style="text-align: center; margin-bottom: 20px;">
  <button id="refreshBtn" style="padding: 8px 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">
    重新生成预测
  </button>
  <div id="predictionStatus" style="display: none; margin-top: 10px; color: #666;"></div>
</div>
<div class="chart-container">
  <canvas id="priceChart"></canvas>
</div>
<div class="model-metrics">
  <h3>模型评估指标</h3>
  <div class="metrics-container">
    <div class="metric-card">
      <div class="metric-title">RMSE (均方根误差)</div>
      <div class="metric-value" id="rmse-value">-</div>
      <div class="metric-desc">预测值与实际值差异的平方根，越小越好</div>
    </div>
    <div class="metric-card">
      <div class="metric-title">MAE (平均绝对误差)</div>
      <div class="metric-value" id="mae-value">-</div>
      <div class="metric-desc">预测值与实际值绝对差异的平均值</div>
    </div>
    <div class="metric-card">
      <div class="metric-title">MAPE (平均绝对百分比误差)</div>
      <div class="metric-value" id="mape-value">-</div>
      <div class="metric-desc">预测误差占实际值的百分比</div>
    </div>
  </div>
  <div class="model-notes">
    <h4>模型说明</h4>
    <p>本预测使用ARIMA(1,1,0)-GARCH(1,1)模型，基于历史房价数据进行训练。模型通过回测验证并应用偏差修正，预测区间代表95%置信水平。</p>
    <p>预测结果仅供参考，不构成投资建议。房价受多种因素影响，包括政策调控、经济周期、供需关系等。</p>
  </div>
</div>

<script>
  // 历史数据
  const rawData = [
    ["2025年5月", 30416, 0.53], ["2025年4月", 30580, 1.13], ["2025年3月", 30930, 1.31],
    ["2025年2月", 31339, 0.93], ["2025年1月", 31052, 0.99], ["2024年12月", 31362, 1.22],
    ["2024年11月", 31749, 0.17], ["2024年10月", 31695, 0.88], ["2024年9月", 31420, 2.05],
    ["2024年8月", 32076, 0.69], ["2024年7月", 32298, 0.04], ["2024年6月", 32284, 0.44],
    ["2024年5月", 32143, 0.95], ["2024年4月", 32452, 1.74], ["2024年3月", 33026, 0.33],
    ["2024年2月", 33136, 0.56], ["2024年1月", 33322, 1.40], ["2023年12月", 33796, 1.20],
    ["2023年11月", 34207, 0.55], ["2023年10月", 34021, 2.59], ["2023年9月", 34927, 0.68],
    ["2023年8月", 35168, 0.71], ["2023年7月", 35420, 0.32], ["2023年6月", 35534, 1.24],
    ["2023年5月", 35979, 2.66], ["2023年4月", 36962, 1.42], ["2023年3月", 37493, 0.30],
    ["2023年2月", 37379, 2.21], ["2023年1月", 36570, 0.62], ["2022年12月", 36800, 1.16],
    ["2022年11月", 36376, 2.36], ["2022年10月", 35538, 0.69], ["2022年9月", 35294, 0.74],
    ["2022年8月", 35034, 0.83], ["2022年7月", 34745, 0.79], ["2022年6月", 34473, 0.88],
    ["2022年5月", 34171, 0.81], ["2022年4月", 33896, 0.76], ["2022年3月", 33640, 0.75],
    ["2022年2月", 33390, 0.77], ["2022年1月", 33134, 0.91], ["2021年12月", 32834, 0.81],
    ["2021年11月", 32571, 0.85], ["2021年10月", 32298, 0.68], ["2021年9月", 32081, 0.53],
    ["2021年8月", 31872, 1.39], ["2021年7月", 31434, 0.32], ["2021年6月", 31535, 2.81],
    ["2021年5月", 30674, 1.00], ["2021年4月", 30370, 2.62], ["2021年3月", 29594, 2.98],
    ["2021年2月", 28739, 2.50], ["2021年1月", 28037, 0.67], ["2020年12月", 27851, 0.69],
    ["2020年11月", 27660, 0.68], ["2020年10月", 27474, 0.71], ["2020年9月", 27280, 0.64],
    ["2020年8月", 27106, 0.65], ["2020年7月", 26931, 0.68], ["2020年6月", 26750, 0.71],
    ["2020年5月", 26561, 0.54], ["2020年4月", 26420, 0.51], ["2020年3月", 26285, 2.49],
    ["2020年2月", 25646, 2.95], ["2020年1月", 26427, 2.13], ["2019年12月", 27002, 0.56],
    ["2019年11月", 27155, 1.15], ["2019年10月", 27471, 2.08], ["2019年9月", 28054, 1.21],
    ["2019年8月", 28398, 1.28], ["2019年7月", 28768, 1.22], ["2019年6月", 28422, 1.30],
    ["2019年5月", 28058, 1.66], ["2019年4月", 27600, 1.38], ["2019年3月", 27986, 0.74],
    ["2019年2月", 28195, 0.10], ["2019年1月", 28224, 1.49], ["2018年12月", 28651, 0.64],
    ["2018年11月", 28836, 0.68], ["2018年10月", 29034, 0.28], ["2018年9月", 29116, 0.29],
    ["2018年8月", 29200, 0.18], ["2018年7月", 29255, 0.63], ["2018年6月", 29074, 1.13],
    ["2018年5月", 28748, 0.19], ["2018年4月", 28694, 0.43], ["2018年3月", 28571, 0.06],
    ["2018年2月", 28554, 0.05], ["2018年1月", 28541, -1], ["2017年12月", 28540, 0.08],
    ["2017年11月", 28562, 1.06], ["2017年10月", 28261, 2.10], ["2017年9月", 27680, 2.12],
    ["2017年8月", 27105, 2.70], ["2017年7月", 26392, 3.33], ["2017年6月", 25543, 0.71],
    ["2017年5月", 25726, 0.85], ["2017年4月", 25509, 1.58], ["2017年3月", 25111, 3.67],
    ["2017年2月", 24222, 2.06], ["2017年1月", 23733, 9.60], ["2016年12月", 21655, 2.21],
    ["2016年11月", 21187, 2.40], ["2016年10月", 20691, 8.63], ["2016年9月", 19048, 2.16],
    ["2016年8月", 18644, 2.20], ["2016年7月", 18243, 0.62], ["2016年6月", 18131, 0.23],
    ["2016年5月", 18089, 0.90], ["2016年4月", 18254, 1.73], ["2016年3月", 17943, 2.23],
    ["2016年2月", 17552, 1.62], ["2016年1月", 17271, 0.15], ["2015年12月", 16080, 1.00],
    ["2015年11月", 16195, -1], ["2015年10月", 16194, 1.00], ["2015年9月", 16413, -1],
    ["2015年8月", 16461, 1.00], ["2015年7月", 16376, 1.00], ["2015年6月", 16240, 1.00],
    ["2015年5月", 16025, -1], ["2015年4月", 16040, 2.00], ["2015年3月", 16312, 1.00],
    ["2015年2月", 16494, 2.00], ["2015年1月", 16807, 1.00], ["2014年12月", 16984, 0.22],
    ["2014年11月", 16946, 0.14], ["2014年10月", 16923, 0.06], ["2014年9月", 16933, 0.69],
    ["2014年8月", 17051, 1.40], ["2014年7月", 17293, 1.87], ["2014年6月", 17623, 2.89],
    ["2014年5月", 18147, 1.66], ["2014年4月", 18453, 0.75], ["2014年3月", 18592, 1.33],
    ["2014年2月", 18843, 0.69], ["2014年1月", 18973, 0.83], ["2013年12月", 19131, 1.67],
    ["2013年11月", 19456, 0.99], ["2013年10月", 19651, 1.20], ["2013年9月", 19889, 0.37],
    ["2013年8月", 19816, 0.47], ["2013年7月", 19909, 0.64], ["2013年6月", 19783, 0.38],
    ["2013年5月", 19709, 0.36], ["2013年4月", 19781, 0.13], ["2013年3月", 19756, 2.23],
    ["2013年2月", 19325, 1.17], ["2013年1月", 19101, 2.07], ["2012年12月", 18713, 1.77],
    ["2012年11月", 18388, 0.69], ["2012年10月", 18516, 0.80], ["2012年9月", 18665, 0.26],
    ["2012年8月", 18617, 0.82], ["2012年7月", 18465, 1.03], ["2012年6月", 18277, 0.11],
    ["2012年5月", 18257, 1.24], ["2012年4月", 18487, 2.02], ["2012年3月", 18868, 0.08],
    ["2012年2月", 18883, 1.43], ["2012年1月", 19157, -1], ["2011年12月", 19721, 3.95],
    ["2011年11月", 20532, 3.19], ["2011年10月", 21208, 3.04], ["2011年9月", 21872, 2.37],
    ["2011年8月", 22404, 1.03], ["2011年7月", 22637, 0.76], ["2011年6月", 22810, 0.67],
    ["2011年5月", 22965, 0.51], ["2011年4月", 23082, 0.39], ["2011年3月", 22992, 2.16],
    ["2011年2月", 22506, 1.57], ["2011年1月", 22159, 1.38], ["2010年12月", 21858, 0.66],
    ["2010年11月", 21715, 0.23], ["2010年10月", 21666, 0.99], ["2010年9月", 21453, 0.61],
    ["2010年8月", 21322, 1.14], ["2010年7月", 21568, 1.54], ["2010年6月", 21906, 0.73],
    ["2010年5月", 22066, 3.82], ["2010年4月", 21254, 9.82], ["2010年3月", 19354, 1.68],
    ["2010年2月", 19035, 1.10], ["2010年1月", 18827, 1.65]
  ];

  // 数据预处理
  const labels = rawData.map(item => item[0].replace("房价", ""));
  const prices = rawData.map(item => item[1]);
  const changes = rawData.map(item => item[2]);

  // 反转数据以按时间顺序显示
  labels.reverse();
  prices.reverse();
  changes.reverse();

  // 数学辅助函数
  Math.stdDev = function(arr) {
    const mean = arr.reduce((a, b) => a + b, 0) / arr.length;
    const squaredDiffs = arr.map(v => Math.pow(v - mean, 2));
    const variance = squaredDiffs.reduce((a, b) => a + b, 0) / arr.length;
    return Math.sqrt(variance);
  };

  Math.variance = function(arr) {
    const mean = arr.reduce((a, b) => a + b, 0) / arr.length;
    return arr.map(v => Math.pow(v - mean, 2)).reduce((a, b) => a + b, 0) / arr.length;
  };

  // 关键转折点分析
  const turningPoints = {
    peaks: [
      { index: 143, label: "2023年5月峰值", type: "high" },
      { index: 135, label: "2021年8月高峰", type: "high" },
      { index: 153, label: "2024年3月高位", type: "high" }
    ],
    valleys: [
      { index: 145, label: "2023年7月谷底", type: "low" },
      { index: 151, label: "2024年1月低点", type: "low" }
    ]
  };

  // 生成未来60个月数据
  const futureLabels = [];
  const futurePrices = [];
  const futureChanges = [];
  const upperBoundPrices = [];
  const lowerBoundPrices = [];
  let lastPrice = prices[prices.length - 1];

  // 计算历史波动特征
  const recentChanges = changes.slice(-60); // 近5年波动数据
  const historicalVolatility = Math.stdDev(recentChanges.map(c => c / 100)) * 100;

  // 回测函数：使用历史数据验证模型
  function backtest(windowSize = 12) {
    const predictions = [];
    const actuals = [];
    
    // 使用滚动窗口进行回测
    for (let i = 60; i < prices.length; i++) {
      const trainPrices = prices.slice(i - 60, i);
      const trainChanges = changes.slice(i - 60, i);
      
      // 使用与generateFutureData相同的预测逻辑
      const historicalReturns = trainChanges.map(c => c / 100);
      const n = historicalReturns.length;
      const meanReturn = historicalReturns.reduce((a, b) => a + b, 0) / n;
      
      // 计算AR(1)系数
      let sumSquared = 0, sumProduct = 0;
      for(let j = 0; j < n-1; j++) {
        sumSquared += Math.pow(historicalReturns[j] - meanReturn, 2);
        sumProduct += (historicalReturns[j] - meanReturn) * (historicalReturns[j+1] - meanReturn);
      }
      const arCoeff = sumProduct / sumSquared;
      
      // 预测下一个时间点
      const lastReturn = historicalReturns[historicalReturns.length - 1];
      const residual = arCoeff * (lastReturn - meanReturn);
      const predictedReturn = meanReturn + residual;
      
      predictions.push(trainPrices[trainPrices.length - 1] * (1 + predictedReturn));
      actuals.push(prices[i]);
    }
    
    // 计算预测误差
    const errors = predictions.map((pred, i) => pred - actuals[i]);
    const rmse = Math.sqrt(errors.map(e => e * e).reduce((a, b) => a + b) / errors.length);
    const mae = errors.map(e => Math.abs(e)).reduce((a, b) => a + b) / errors.length;
    const mape = errors.map((e, i) => Math.abs(e / actuals[i])).reduce((a, b) => a + b) / errors.length * 100;
    
    return {
      predictions,
      actuals,
      metrics: { rmse, mae, mape },
      errors
    };
  }

  // 偏差修正函数：根据回测结果修正预测
  function biasCorrection(backTestResults) {
    const { errors } = backTestResults;
    const meanBias = errors.reduce((a, b) => a + b, 0) / errors.length;
    const stdBias = Math.stdDev(errors);
    
    return {
      biasAdjustment: meanBias,
      uncertaintyRange: stdBias * 1.96 // 95% 置信区间
    };
  }

  // 改进的预测模型
  function generateFutureData(months) {
    if (!Array.isArray(changes) || changes.length === 0) {
      console.error("Invalid input data: 'changes' must be a non-empty array.");
      return;
    }

    // 执行回测和偏差修正
    const backTestResults = backtest();
    console.log('回测指标:', backTestResults.metrics);
    const { biasAdjustment, uncertaintyRange } = biasCorrection(backTestResults);
    console.log('偏差修正:', { biasAdjustment, uncertaintyRange });

    // 存储回测结果供图表使用
    window.backTestResults = backTestResults;
    window.predictionUncertainty = uncertaintyRange;

    // 数据预处理
    const historicalReturns = changes.slice(-60).map(c => c / 100); // 获取近5年月度收益率
    const n = historicalReturns.length;
    
    // 计算基础统计量
    const meanReturn = historicalReturns.reduce((a, b) => a + b, 0) / n;
    let sumSquared = 0, sumProduct = 0;
    
    // AR(1)系数（简化版Yule-Walker方法）
    let arCoeff = 0;
    for(let i=0; i<n-1; i++) {
      sumSquared += Math.pow(historicalReturns[i] - meanReturn, 2);
      sumProduct += (historicalReturns[i] - meanReturn) * (historicalReturns[i+1] - meanReturn);
    }
    arCoeff = sumProduct / sumSquared;
    
    // GARCH(1,1)参数（建议通过MLE估计，此处使用典型值）
    const omega = 0.000002,  // 长期波动率基线
          alpha = 0.07,      // 新息冲击敏感度
          beta = 0.92;       // 波动率持续性
    
    // 预测未来数据
    let price = lastPrice;
    let lastVariance = historicalReturns
                        .map(r => Math.pow(r - meanReturn, 2))
                        .reduce((a, b) => a + b, 0) / n;
    
    for (let i = 0; i < months; i++) {
      // GARCH预测方差
      const epsilonSquared = Math.pow(historicalReturns[(i) % n] - meanReturn, 2);
      const predictedVariance = omega + alpha * epsilonSquared + beta * lastVariance;
      const predictedVolatility = Math.sqrt(predictedVariance);
      
      // ARIMA(1,1,0)预测
      const residual = arCoeff * (historicalReturns[(i) % n] - meanReturn);
      const drift = meanReturn + residual;
      
      // 确定性预测 (移除随机扰动)
      const rawChange = drift * 100;
      
      // 应用偏差修正
      const correctedChange = rawChange - (biasAdjustment / price * 100);
      
      // 更新状态
      price = parseFloat((price * (1 + correctedChange / 100)).toFixed(2));
      
      // 计算预测区间
      const upperPrice = parseFloat((price * (1 + uncertaintyRange / price)).toFixed(2));
      const lowerPrice = parseFloat((price * (1 - uncertaintyRange / price)).toFixed(2));
      lastVariance = predictedVariance;
      
      // 时间戳计算
      const currentDate = new Date('2025-06');
      currentDate.setMonth(currentDate.getMonth() + i + 1);
      const year = currentDate.getFullYear();
      const month = String(currentDate.getMonth() + 1).padStart(2, '0');

      futureLabels.push(`${year}年${month}月`);
      futurePrices.push(price);
      futureChanges.push(correctedChange);
      upperBoundPrices.push(upperPrice);
      lowerBoundPrices.push(lowerPrice);
    }
  }

  generateFutureData(60); // 生成60个月预测数据

  // 合并完整数据集
  const fullLabels = [...labels, ...futureLabels];
  const fullPrices = [...prices, ...futurePrices];
  const fullChanges = [...changes, ...futureChanges];

  // 阶段划分
  const stageRanges = [
    { startIndex: 0, endIndex: 47, label: "政策刺激上涨", color: 'rgba(255, 99, 132, 0.1)' },
    { startIndex: 48, endIndex: 83, label: "市场调整期", color: 'rgba(255, 206, 86, 0.1)' },
    { startIndex: 84, endIndex: 143, label: "严格调控期", color: 'rgba(75, 192, 192, 0.1)' },
    { startIndex: 144, endIndex: labels.length - 1, label: "深度调整期", color: 'rgba(153, 102, 255, 0.1)' },
    { startIndex: labels.length, endIndex: fullLabels.length - 1, label: "ARIMA(1,1,0)-GARCH(1,1)预测", color: 'rgba(102, 255, 102, 0.1)' }
  ];

  // 创建图表配置
  const chartConfig = {
    type: 'line',
    data: {
      labels: fullLabels,
      datasets: [
        {
          label: '历史均价',
          data: prices,
          borderColor: 'rgb(54, 162, 235)',
          backgroundColor: 'rgba(54, 162, 235, 0.1)',
          fill: true,
          tension: 0.3,
          segment: {
            borderColor: ctx => 'rgb(54, 162, 235)'
          }
        },
        {
          label: '预测均价',
          data: [...Array(prices.length).fill(null), ...futurePrices],
          borderColor: 'rgb(75, 192, 192)',
          backgroundColor: 'rgba(75, 192, 192, 0.1)',
          fill: true,
          tension: 0.3,
          borderDash: [5, 5]
        },
        {
          label: '预测区间上限',
          data: [...Array(prices.length).fill(null), ...upperBoundPrices],
          borderColor: 'rgba(255, 99, 132, 0.5)',
          backgroundColor: 'rgba(255, 99, 132, 0.1)',
          fill: false,
          tension: 0.3,
          borderDash: [5, 5],
          pointRadius: 0
        },
        {
          label: '预测区间下限',
          data: [...Array(prices.length).fill(null), ...lowerBoundPrices],
          borderColor: 'rgba(255, 99, 132, 0.5)',
          backgroundColor: 'rgba(255, 99, 132, 0.1)',
          fill: 1,
          tension: 0.3,
          borderDash: [5, 5],
          pointRadius: 0
        }
      ]
    },
    options: {
      responsive: true,
      plugins: {
        title: {
          display: true,
          text: '杭州二手房市场均价趋势分析与预测（2010-2030）',
          font: { size: 18 }
        },
        subtitle: {
          display: true,
          text: '基于ARIMA(1,1,0)-GARCH(1,1)模型，包含95%置信区间',
          font: { size: 14 },
          padding: { bottom: 10 }
        },
        tooltip: {
          mode: 'index',
          intersect: false,
          callbacks: {
            label: function(context) {
              const label = context.dataset.label || '';
              const value = context.parsed.y;
              if (label.includes('预测')) {
                return `${label}: ${value.toFixed(0)}元/㎡`;
              } else {
                const index = context.dataIndex;
                const change = fullChanges[index];
                return `${label}: ${value.toFixed(0)}元/㎡ (环比: ${change?.toFixed(2) || 0}%)`;
              }
            },
            footer: function(tooltipItems) {
              const index = tooltipItems[0].dataIndex;
              if (index >= prices.length) {
                const metrics = window.backTestResults?.metrics;
                if (metrics) {
                  return [
                    '',
                    `模型评估指标:`,
                    `RMSE: ${metrics.rmse.toFixed(0)}`,
                    `MAPE: ${metrics.mape.toFixed(2)}%`
                  ];
                }
              }
              return '';
            }
          }
        },
        annotation: {
          annotations: {}
        },
        legend: {
          display: true,
          labels: {
            usePointStyle: true,
            generateLabels: (chart) => [
              { text: '历史均价', fillStyle: 'rgb(54, 162, 235)', strokeStyle: 'rgb(54, 162, 235)', pointStyle: 'circle' },
              { text: '预测均价', fillStyle: 'rgb(75, 192, 192)', strokeStyle: 'rgb(75, 192, 192)', pointStyle: 'circle', borderDash: [5,5] },
              { text: '95%预测区间', fillStyle: 'rgba(255, 99, 132, 0.1)', strokeStyle: 'rgba(255, 99, 132, 0.5)', pointStyle: 'rect' }
            ]
          }
        }
      },
      scales: {
        x: {
          type: 'category',
          title: { display: true, text: '时间', font: { size: 14 } },
          ticks: {
            autoSkip: true,
            maxTicksLimit: 30,
            rotation: 45
          }
        },
        y: {
          beginAtZero: false,
          title: { display: true, text: '价格 (元/㎡)', font: { size: 14 } },
          grid: { color: 'rgba(0, 0, 0, 0.05)' }
        }
      }
    },
    plugins: []
  };

  // 更新模型评估指标显示
  function updateMetrics(metrics) {
    if (metrics) {
      document.getElementById('rmse-value').textContent = metrics.rmse.toFixed(0) + ' 元/㎡';
      document.getElementById('mae-value').textContent = metrics.mae.toFixed(0) + ' 元/㎡';
      document.getElementById('mape-value').textContent = metrics.mape.toFixed(2) + '%';
    }
  }

  // 更新图表函数
  function updateChart() {
    document.getElementById('predictionStatus').textContent = '正在计算预测模型...';
    document.getElementById('predictionStatus').style.display = 'block';
    document.getElementById('predictionStatus').style.color = '#666';
    
    try {
      // 清空之前的数据
      futureLabels.length = 0;
      futurePrices.length = 0;
      futureChanges.length = 0;
      upperBoundPrices.length = 0;
      lowerBoundPrices.length = 0;
      
      // 生成新的预测数据
      generateFutureData(60);
      
      // 更新图表数据
      chart.data.labels = [...labels, ...futureLabels];
      chart.data.datasets[0].data = prices;
      chart.data.datasets[1].data = [...Array(prices.length).fill(null), ...futurePrices];
      chart.data.datasets[2].data = [...Array(prices.length).fill(null), ...upperBoundPrices];
      chart.data.datasets[3].data = [...Array(prices.length).fill(null), ...lowerBoundPrices];
      chart.update();
      
      // 更新模型评估指标
      if (window.backTestResults && window.backTestResults.metrics) {
        updateMetrics(window.backTestResults.metrics);
      }
      
      document.getElementById('predictionStatus').textContent = '预测完成';
      setTimeout(() => {
        document.getElementById('predictionStatus').style.display = 'none';
      }, 2000);
    } catch (error) {
      console.error('预测模型错误:', error);
      document.getElementById('predictionStatus').textContent = '预测失败: ' + error.message;
      document.getElementById('predictionStatus').style.color = 'red';
    }
  }

  // 初始化图表
  const ctx = document.getElementById('priceChart').getContext('2d');
  const chart = new Chart(ctx, chartConfig);
  
  // 初始化模型评估指标
  if (window.backTestResults && window.backTestResults.metrics) {
    updateMetrics(window.backTestResults.metrics);
  }
  
  // 添加按钮事件监听
  document.getElementById('refreshBtn').addEventListener('click', updateChart);

</script>

</body>
</html>